#include "plotdata.h"
#include <QDebug>
_XYList::_XYList()
{
    m_Type=_TICKERTYPE::YAxis_L;
    m_MaxPointCount=100000;
    m_Color=QColor(255,255,255);
    m_Visible=true;
    m_MaxValue.Key=-1;
    m_MaxValue.Value=-1;
    m_MinValue.Key=-1;
    m_MinValue.Value=-1;
    m_removeCount=0;
    setPointCountMax(m_MaxPointCount);
}

int _XYList::Count()
{
    return m_CoodValue.size()-m_removeCount;
}

int _XYList::CountAll()
{
    return m_CoodValue.size();
}

_COORDINATEVALUE &_XYList::getPoint(int index)
{
    if(index>=0&&index<Count())
    {
        return m_CoodValue[index];
    }
    return m_CoodValue[index];
}

void _XYList::addData(const double Key, const double Value)
{
    _COORDINATEVALUE TmpCoorValue;
    TmpCoorValue.Key=Key;
    TmpCoorValue.Value=Value;
    m_CoodValue.append(TmpCoorValue);
    if(m_CoodValue.size()>m_MaxPointCount)
    {
        removefirst();
    }
    if(m_CoodValue.size()==1){
        m_MaxValue.Key=TmpCoorValue.Key;
        m_MaxValue.Value=TmpCoorValue.Value;
        m_MinValue.Key=TmpCoorValue.Key;
        m_MinValue.Value=TmpCoorValue.Value;
    }else{
        if(TmpCoorValue.Key>=m_MaxValue.Key){ m_MaxValue.Key=TmpCoorValue.Key; }
        if(TmpCoorValue.Value>=m_MaxValue.Value){ m_MaxValue.Value=TmpCoorValue.Value; }
        if(TmpCoorValue.Key<=m_MinValue.Key){ m_MinValue.Key=TmpCoorValue.Key; }
        if(TmpCoorValue.Value<=m_MinValue.Value){ m_MinValue.Value=TmpCoorValue.Value; }
    }
}

void _XYList::removefirst()
{
    m_removeCount++;
    const int totalAlloc = m_CoodValue.capacity();//总的空间
    //const int freeSize = totalAlloc-m_CoodValue.size();//空闲空间
    const int usedSize = size();//使用的实际空间
    bool shrinkPreAllocation = false;
    if (totalAlloc > 650000) // if allocation is larger, shrink earlier with respect to total used size
    {
      //移除的倍数目大于实际使用数目的0.1倍时重新分配大小
      shrinkPreAllocation = m_removeCount > usedSize*0.1;
    } else if (totalAlloc > 1000) // below 10 MiB raw data be generous with preallocated memory, below 1k points don't even bother
    {
      //移除的倍数目大于实际使用数目的1倍时重新分配大小
      shrinkPreAllocation = m_removeCount > usedSize*1; // preallocation can grow into postallocation, so can be smaller
    }
   // qDebug()<<m_removeCount<<usedSize*1.5<<totalAlloc<<freeSize;
    //qDebug()<<"performAutoSqueeze"<<(shrinkPreAllocation || shrinkPostAllocation)<<shrinkPreAllocation<<shrinkPostAllocation<<usedSize<<totalAlloc;
    //满足重新分配控件要求，则重新分配
    if (shrinkPreAllocation)//防止内存过大，回收内存
    {
      if (m_removeCount > 0)
      {
//        int size1=size();
//        int size2=m_CoodValue.size();
        std::copy(constBegIte(), constEndIte(), m_CoodValue.begin());
        m_CoodValue.resize(size());
        m_CoodValue.squeeze();//释放空闲的内存
        m_removeCount = 0;
        //qDebug()<<"*****************----->"<<size1<<size2<<size()<<m_CoodValue.size();
      }
    }
}

void _XYList::cleanBuff()
{
    if(m_CoodValue.size()>1000){
        m_CoodValue.clear();//不释放申请的内存空间
        m_CoodValue.squeeze();//释放掉没有用到的空间
    }else{
        m_CoodValue.clear();//不释放申请的内存空间
    }
    m_removeCount=0;
}

void _XYList::setPointCountMax(int Count)
{
    m_MaxPointCount=Count;

}

int _XYList::getBegindex(const double &TmpKey)
{
    int Count=this->CountAll();
    int RetIndex=m_removeCount;
    if(Count==0){ return -1; }
    QVector<_COORDINATEVALUE>::const_iterator begIte=this->constBegIte();
    if(begIte->Key>=TmpKey){
        return RetIndex;
    }
    RetIndex=getCoorToIndex(TmpKey);
    return RetIndex;
}

int _XYList::getEndindex(const double &TmpKey)
{
    int Count=this->CountAll();
    int RetIndex=m_removeCount;
    int Right=Count-1;

    if(Count==0){ return -1; }
   // qDebug()<<(qint64)this->data()->last().Key<<(qint64)TmpKey;
    if(this->data()->last().Key<=TmpKey){
        return Right;
    }
    RetIndex=getCoorToIndex(TmpKey);
    return RetIndex;
}

int _XYList::getCoorToIndex(const double &TmpKey)
{
    int Count=this->CountAll();
    int RetIndex=0;
    int Middle=0;
    int Right=Count-1;
    int Left=m_removeCount;

    if(Count==0){ return -1; }

    _COORDINATEVALUE coorValue;
    while(Right > Left)//通过二分法查找开始坐标值索引
    {
        Middle=(Left+Right)/2;
        coorValue=m_CoodValue[Middle];
        if(coorValue.Key>TmpKey){
            Right=Middle;
        }
        if(coorValue.Key<TmpKey){
            Left=Middle;
        }
        if(coorValue.Key==TmpKey){
            RetIndex=Middle;
            break;
        }
        if(Right - Left <= 1)
        {
            RetIndex=Left;
            break;
        }
    }
    return RetIndex;
}

QVector<_COORDINATEVALUE> *_XYList::data()
{
    return &m_CoodValue;
}
//===================================================================================================================
void Ticker::setRangeBeg(const double &Value)
{
    //if(Value<-1000000000.0){ return; }
    if(Value>=m_RangeEnd)
    {
        m_RangeBeg=m_RangeEnd-1;
    }else{
        m_RangeBeg=Value;
    }
}

void Ticker::setRangeEnd(const double &Value)
{
    //if(Value>1000000000.0){ return; }
    if(Value<=m_RangeBeg)
    {
        m_RangeEnd=m_RangeBeg+1;
    }else{
        m_RangeEnd=Value;
    }
}

void Ticker::setRange(const double &BegValue,const double &EndValue)
{
    setRangeEnd(EndValue);
    setRangeBeg(BegValue);  
}

void Ticker::moveRange(const double &Value)
{
     m_RangeEnd=m_RangeEnd+Value;
     m_RangeBeg=m_RangeBeg+Value;
}

void Ticker::moveRangePercent(const double &Value)
{
    m_RangeBeg+=((m_RangeEnd-m_RangeBeg)*Value);
    m_RangeEnd+=((m_RangeEnd-m_RangeBeg)*Value);
}

void Ticker::setZoom(const double value)
{
    InitScale();
    getScale()._siteVal=getRangeMidvalue();
    setScaleCoor(value);
}

void Ticker::InitScale()
{
    m_Scale._begVal=m_RangeBeg;
    m_Scale._endVal=m_RangeEnd;
}

void Ticker::setScaleCoor(const double scaleFactor)
{
    if(scaleFactor==1){ return ; }
    double begval=0.0;
    double endval=0.0;
    if(scaleFactor<1)//缩小
    {
       begval=m_Scale._begVal-(m_Scale._siteVal-m_Scale._begVal)*(1-scaleFactor);
       endval=m_Scale._endVal+(m_Scale._endVal-m_Scale._siteVal)*(1-scaleFactor);
    }else{
        begval=m_Scale._siteVal-(m_Scale._siteVal-m_Scale._begVal)/scaleFactor;
        endval=m_Scale._siteVal+(m_Scale._endVal-m_Scale._siteVal)/scaleFactor;
    }
    setRangeBeg(begval);
    setRangeEnd(endval);
}
